--[[
   F5-10.0.116.206:80 POST/GET方式传递key/value参数，以XML格式返回结果，协议文档参见《浙商银行手机银行新版接口设计.docx》
]]
require("apm_core")
require("ApmXml")
local httpUtil = require("ApmHttpUtil")

local G_DEBUG = false

if G_DEBUG == false then
    function logDebug(fmt,...) end
    function logInfo(fmt,...) end
    function logWarn(fmt,...) end
    function logError(fmt,...) end
    function logFatal(fmt,...) end
end

local KRED='\x1B[0;31m'
local KSALMON='\x1B[1;31m'
local KGREEN='\x1B[0;32m'
local KLIMEGREEN='\x1B[1;32m'
local KYELLOW='\x1B[0;33m'
local KORANGE='\x1B[0;34m'
local KBLUE='\x1B[1;34m'
local KMAGENTA='\x1B[0;35m'
local KPINK='\x1B[1;35m'
local KCYAN='\x1B[0;36m'
local RESET='\x1B[0m'

local t_xml_tree
local s_businessAcceptId
local s_rspcode
local s_rspmsg

local t_dse_operationName = {
    login = "用户登录",
	signMobileBankSrvOp = {
		paramName = "cmd",
		["0"] = "注册信息校验",
		["1"] = "注册",
	},
	checkAccPassWordSrvOp = "校验账户密码",
	queryMBAcctListSrvOp = "查询下挂账户及余额",
	queryUnionBankInfoSrvOp = "查询省份城市网点号",
	sendMsgSrvOp = "发送短信",
	updateMBLogonPwdSrvOp = "信用卡登录密码修改",
	resetMBPasswordSrvOp = "登录密码重置",
	logonResetPwdSrvOp = "首次登录密码重置",
	checkMobileSrvOp = "根据证件号码检查手机号",
	creditQrySrvOp = "客户持有信用卡查询",
	creditAccQrySrvOp = "信用卡账户信息查询",
	creditAcctPtSrvOp = "信用卡积分查询、调整",
	creditActSrvOp = "信用卡激活",
	creditUnsettledBillQrySrvOp = "信用卡未出账单查询",
	creditApplySttQrySrvOp = "信用卡申请进度查询",
	creditAutoRepaySrvOp = "信用卡自扣还款账号查询和维护",
	creditBillDetailQrySrvOp = "信用卡账单明细查询",
	creditcrCustQPasswdSrvOp = "信用卡客户级查询密码申请/重置",
	creditcrTxnPasswdSrvOp = "信用卡交易密码申请/重置",
	creditCustQPasswdSrvOp = "信用卡查询密码修改",
	creditTxnPasswdSrvOp = "信用卡交易密码修改",
	creditInfoQrySrvOp = "信用卡卡信息查询",
	creditLossSrvOp = "信用卡挂失",
	creditQccStmtFirstSrvOp = "信用卡账单头查询",
	creditRepaySrvOp = "信用卡还款交易",
	billSendSrvOp = "信用卡账单寄送设置",
	financeQryBuySrvOp = {
		paramName = "cmd",
		["0"] = "理财产品查询",
		["6"] = "理财产品查询",
		["3"] = "理财产品账号余额查询",
		["4"] = "理财产品购买",
	},
	myFinanceProductQrySrvOp = {
		paramName = "opFlag",
		["0"] = "当前持有",
		["1"] = "赎回",
	},
	myFinanceProductRepealSrvOp = {
		paramName = "opFlag",
		["0"] = "当前委托",
		["2"] = "撤单",
	},
	qryMyFinanceDetailSrvOp = "历史交易查询",
	newCxlcpgSrvOp = "风险等级查询",
	newTjpcjgSrvOp = "风险等级修改",
	financialTransferSrvOp = {
		paramName = "cmd",
		["0"] = "可转让和转让中查询",
		["1"] = "理财转让",
		["2"] = "转让中的理财",
		["4"] = "转让中的理财",
		["5"] = "转让中的理财",
		["3"] = "转让委托撤消",
		["7"] = "理财转让购买",
	},
	loanSelSrvOp = "贷款查询",
	advanceRepaymentOp = "客户持有信用卡查询",
	returnMonListSrvOp = "贷款明细查询",
	calculatorLoanOp = "贷款试算",
	withdrawInfoConfirmOp = "提款信息确认",
	loanPlanSrvOp = "贷款试算",
	integralYueSrvOp = "积分查询",
	integralTranSrvOp = "积分转账",
	integralListSrvOp = "积分明细查询",
	myAssetsLiabilityOp = "账户总览",
	lossOfAccSrvOp = "账户挂失解挂",
	queryTransListSrvOp = "账户交易明细",
	resetAccPasswordSrvOp = "账户密码重置",
	creditStartDealSrvOp = "IC卡启用",
	msgManageOp = "余额变动通知",
	myZjbSrvOp = {
		paramName = "cmd",
		["0"] = "我的增金宝",
		["3"] = "增金宝万份收益",
		["4"] = "增金宝累计收益",
		["5"] = "查询增金宝行情信息",
	},
	zjbTranDetailQryOp = "增金宝交易明细查询",
	myZlbSrvOp = {
		paramName = "cmd",
		default = "我的涌金钱包1号",
		["0"] = "我的涌金钱包1号",
		["2"] = "涌金钱包1号平均收益",
	},
	zlbTranDetailQryOp = {
		paramName = "cmd",
		["1"] = "涌金钱包1号交易明细",
		["3"] = "涌金钱包1号累计收益",
	},
	queryDqtz2HqSrvOp = "定期通知存款查询",
	tzNotifySrvOp = "发起通知",
	tzCancelSrvOp = "通知撤消",
	hq2DqtzSrvOp = "活期转定期/通知",
	dqtz2HqSrvOp = "定期/通知转活期",
	queryInterestRateSrvOp = "年利率",
	taFundSignSrvOp = "签约开户",
	qrySignAgreementSrvOp = {
		paramName = "opFlag",
		["0"] = "客户信息查询",
		["1"] = "签约账号查询",
	},
	qryFinanceOnSaleSrvOp = "查询在售产品",
	purchaseFinanceSrvOp = "理财购买",
	qryMyFinanceSrvOp = "查询当前持有",
	qryMyBailFinanceSrvOp = "查询当前委托",
	qryFinanceDetilSrvOp = {
		paramName = "opType",
		["1"] = "查询历史持有",
		["2"] = "查询持有产品详情",
	},
	taDivModeSrvOp = "分红方式变更",
}

local function parseIp(ip)
    local _, _, value = string.find(ip, "(%d+.%d+)$")
    return value == nil and "" or value
end

--- 协议判断
-- return
-- true; false
local function protocol_detect(s_payload)
    if s_payload == nil then return false end

    t_xml_tree = ApmXml.load(s_payload, "UTF-8")

    if t_xml_tree == nil then return false end

    return ApmXml.getValue(t_xml_tree, "/mobileBank") ~= nil
end

--- 解析响应
-- return
-- true: 解析成功; false: 解析失败
local function parse_response(ApmData)
    -- 交易返回代码
    s_rspcode = ApmXml.getValue(t_xml_tree, ".//response/errorNo/text()")
	
    -- 交易返回信息
    s_rspmsg = ApmXml.getValue(t_xml_tree, ".//response/errorMsg/text()")
    if s_rspmsg ~= nil then
        s_rspmsg = string.trim(s_rspmsg)
    end

    return true
end

--- main
function post_analysis()
    local ApmData = require("ApmData")
    if ApmData.getL7Proto() ~= 80 then return end
    if ApmData.getMsgType() ~= 1 then return end

	local s_dse_operationName, s_dse_operationName_cn
    local s_xml_resp
	
	--logInfo("param:[%s]", ApmData.getField("request.http.body.1", 1))
	local t_kv = httpUtil.getParams(ApmData)
    if t_kv ~= nil then
        s_dse_operationName = t_kv["dse_operationName"]
		if s_dse_operationName == nil and t_kv["logon_pwd"] ~= nil then
			s_dse_operationName = "login"
		end
		
		if s_dse_operationName ~= nil then
			s_dse_operationName = string.trim(s_dse_operationName)
			s_dse_operationName_cn = t_dse_operationName[s_dse_operationName]
			if s_dse_operationName_cn == nil then
				s_dse_operationName_cn = s_dse_operationName
				--logError("unknown 1 dse_operationName:[%s] title:[%s] param:[%s]", s_dse_operationName, ApmData.getField("transaction.title", 1), ApmData.getField("request.http.body.1", 1))
			elseif type(s_dse_operationName_cn) == "table" then
				local s_paramName = s_dse_operationName_cn["paramName"]
				if s_paramName ~= nil then
					local s_cmd = t_kv[s_paramName]
					local s_tmp = s_dse_operationName_cn[s_cmd]
					if s_tmp == nil then
						if s_dse_operationName_cn["default"] ~= nil then
							s_dse_operationName_cn = s_dse_operationName_cn["default"]
						else
							s_dse_operationName_cn = s_dse_operationName
							logError("unknown 2 dse_operationName:[%s] title:[%s] param:[%s]", s_dse_operationName, ApmData.getField("transaction.title", 1), ApmData.getField("request.http.body.1", 1))
						end
					else
						s_dse_operationName_cn = s_tmp
					end
				else
					s_dse_operationName_cn = s_dse_operationName
					logError("unknown dse_operationName flag:[%s]", s_dse_operationName)
				end
			end
		end
    end

	s_xml_resp = ApmData.getField("response.http.body.1", 1)
    if s_xml_resp ~= nil then
        s_xml_resp = string.trim(s_xml_resp)
        if protocol_detect(s_xml_resp) then
            parse_response(ApmData)
		else
			logInfo("Response:["..KBLUE.."%s"..RESET.."]", s_xml_resp)
        end
    end
	
	--logError("dse_operationName:[%s] title:[%s] param:[%s]", s_dse_operationName, ApmData.getField("transaction.title", 1), ApmData.getField("request.http.body.1", 1))
	--logInfo("Response:["..KBLUE.."%s"..RESET.."]", s_xml_resp)

	if s_dse_operationName == nil then
        logInfo("title:[%s] param:[%s]", ApmData.getField("transaction.title", 1), ApmData.getField("request.http.body.1", 1))
    elseif s_rspcode == nil then
        logInfo("s_rspcode is nil RESP:[%s]", s_soap_resp)
    else
        ApmData.replaceField("transaction.type_code", s_dse_operationName)
        ApmData.replaceField("transaction.type_name", s_dse_operationName_cn)
        --ApmData.replaceField("transaction.title", s_dse_operationName_cn)

        ApmData.replaceField("response.code_string", s_rspcode)
        ApmData.delFields("response.code")

        if s_rspmsg ~= nil then
            ApmData.replaceField("response.error_message", s_rspmsg)
        end

--        if s_businessAcceptId ~= nil then
--            ApmData.replaceField("transaction.code", s_businessAcceptId)
--        end
        logInfo("mobapp(%s:%d->%s:%d) operation:%s|name:%s|ret:%s|%s",
            parseIp(ApmData.getSrcIp()),
            ApmData.getSrcPort(),
            parseIp(ApmData.getDstIp()),
            ApmData.getDstPort(),
            s_dse_operationName,
            s_dse_operationName_cn,
            s_rspcode,
            s_rspmsg
        )
    end
	
    return
end
--手机网银
--v1.0.1
